﻿using AbpMvc.Demo.Categories;
using AbpMvc.Demo.Permissions;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace AbpMvc.Demo.Products
{
    public class ProductService : DemoAppService, IProductService
    {
        private readonly IRepository<Product, Guid> productRepository;
        private readonly IUnitOfWorkManager unitOfWorkManager;
        private readonly IRepository<Category, Guid> categoryRepository;

        public ProductService(IRepository<Product, Guid> productRepository
            , IUnitOfWorkManager unitOfWorkManager
            , IRepository<Category, Guid> categoryRepository)
        {
            this.productRepository = productRepository;
            this.unitOfWorkManager = unitOfWorkManager;
            this.categoryRepository = categoryRepository;
        }
        [Authorize(DemoPermissions.ProductsManagementCreation)]
        public async Task CreateAsync(CreateOrUpdateProductDto input)
        {
            var product = ObjectMapper.Map<CreateOrUpdateProductDto, Product>(input);
            await productRepository.InsertAsync(product);
        }
        [Authorize(DemoPermissions.ProductsManagementDeletion)]
        public async Task DeleteAsync(Guid id)
        {
            await productRepository.DeleteAsync(id);
        }

        public async Task<ProductDto> GetAsync(Guid id)
        {
            return ObjectMapper.Map<Product, ProductDto>(await productRepository.GetAsync(id));
        }

        public async Task<ListResultDto<CategoryLookupDto>> GetCategoriesAsync()
        {
            var categories = await categoryRepository.GetListAsync();
            var categoryLookupDto = ObjectMapper.Map<List<Category>, List<CategoryLookupDto>>(categories);

            return new ListResultDto<CategoryLookupDto>(categoryLookupDto);
        }

        public async Task<PagedResultDto<ProductDto>> GetListAsync(PagedAndSortedResultRequestDto input)
        {
            var queryable = await productRepository.WithDetailsAsync(x => x.Category);

            queryable = queryable.Skip(input.SkipCount)
                .Take(input.MaxResultCount)
                .OrderBy(input.Sorting ?? nameof(Product.Name));
            var products = await AsyncExecuter.ToListAsync(queryable);
            var count = await productRepository.GetCountAsync();
            return new PagedResultDto<ProductDto>(count, ObjectMapper.Map<List<Product>, List<ProductDto>>(products));

        }

        public async Task UpdateAsync(Guid id, CreateOrUpdateProductDto input)
        {
            var product = await productRepository.GetAsync(id);
            ObjectMapper.Map(input, product);
        }
    }
}
